////////////////////////////////////////////////////////////////////////////////////////////////////
/// Copyright (c) 2009 - 2010 RacoonStudios
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy of this
/// software and associated documentation files (the "Software"), to deal in the Software
/// without restriction, including without limitation the rights to use, copy, modify, merge,
/// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
/// to whom the Software is furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all copies or
/// substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
/// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
/// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
/// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
/// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
/// DEALINGS IN THE SOFTWARE.
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once
#ifndef fcc_h__
#define fcc_h__

#include "core/types.h"
#include "helper/string.h"

namespace Helper
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// \class	FCC
	///
	/// \brief	This si simply a so called FourCharsContainer and that's it.
	///			Mainly we are using this type of container for our Rtti system.
	///
	/// \author	khaos
	/// \date	14.12.2009
	////////////////////////////////////////////////////////////////////////////////////////////////////
	class FCC
	{
		public:

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	FCC()
			///
			/// \brief	Default constructor. 
			///
			/// \author	khaos
			/// \date	14.12.2009
			////////////////////////////////////////////////////////////////////////////////////////////////////
			FCC();

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	FCC(uint fcc)
			///
			/// \brief	Constructor. 
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param	[in]	fcc	The fcc objectas uint.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			FCC(uint fcc);

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	FCC(const String & fcc)
			///
			/// \brief	Constructor. 
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param	[in]	fcc	The fcc object as String.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			FCC(const String & fcc);




			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void operator= (const FCC & rhs)
			///
			/// \brief	Copy operator. 
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param	[in]	rhs	The right hand side object. 
			////////////////////////////////////////////////////////////////////////////////////////////////////
			void operator = (const FCC & rhs);

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void operator= (uint & fcc)
			///
			/// \brief	Copy operator. 
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param	[in]	fcc	the fcc we want to set.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			void operator = (uint & fcc);

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool operator== (const FCC & rhs) const
			///
			/// \brief	Equality operator. 
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param	[in]	rhs	The right hand side object. 
			///
			/// \return	True if both objects are equal, otherwise false.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool operator == (const FCC & rhs) const;

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool operator!= (const FCC & rhs) const
			///
			/// \brief	Inequality operator. 
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param	[in]	rhs	The right hand side object. 
			///
			/// \return	True if both objects are inequal, otherwise false.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool operator != (const FCC & rhs) const;

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool operator< (const FCC & rhs) const
			///
			/// \brief	a value indicating whether the operator<(const fcc &rhs)const. 
			///
			/// \param	[in]	rhs The right hand side object.
			///
			/// \return	True if this object is lesser than the specified, otherwise false.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool operator < (const FCC & rhs) const;

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool operator> (const FCC & rhs) const
			///
			/// \brief	Greater-than comparison operator. 
			///
			/// \author	khaos
			/// \date	04.01.2010
			///
			/// \param	[in]	rhs	The right hand side object. 
			///
			/// \return	True if this object is greater than the specified, otherwise false.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool operator > (const FCC & rhs) const;

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool operator<= (const FCC & rhs) const
			///
			/// \brief	 a value indicating whether the operator<=(const fcc &rhs)const. 
			///
			///	\param	[in]	rhs	The right hand side object. 
			///
			/// \return	True if this object is lesser or equal the specified, otherwise false.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool operator <= (const FCC & rhs) const;

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool operator>= (const FCC & rhs) const
			///
			/// \brief	Greater-than-or-equal comparison operator. 
			///
			/// \author	khaos
			/// \date	04.01.2010
			///
			/// \param	[in]	rhs	The right hand side object. 
			///
			/// \return	True if this object is greater or equal the specified, otherwise false.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool operator >= (const FCC & rhs) const;




			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void Set(uint & fcc)
			///
			/// \brief	Resets the FCC with the specified value.
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param [in]	fcc	The value the FCC should have.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			void Set(uint & fcc);

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void Set(const String & fcc)
			///
			/// \brief	Resets the FCC with the specified value.
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \param	[in]	fcc	The value the FCC should have.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			void Set(const String & fcc);





			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	bool IsValid() const
			///
			/// \brief	Returns true if this FCC is valid, otherwise false.
			///
			/// \author	khaos
			/// \date	14.12.2009
			///
			/// \return	True if this FCC is valid, otherwise false.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			bool IsValid() const;

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void Clear()
			///
			/// \brief	Clears this FCC an resets its values.
			///
			/// \author	khaos
			/// \date	14.12.2009
			////////////////////////////////////////////////////////////////////////////////////////////////////
			void Clear();

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	uint GetAsUint() const
			///
			/// \brief	Returns the FCC as uint.
			///
			/// \author	Markus
			/// \date	22.01.2010
			///
			/// \return	Returns this object as uint.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			uint GetAsUint() const;

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	Helper::String GetAsString() const
			///
			/// \brief	Returns this FCC as String.
			///
			/// \author	Markus
			/// \date	22.01.2010
			///
			/// \return	Returns this object as String.
			////////////////////////////////////////////////////////////////////////////////////////////////////
			Helper::String GetAsString() const;

		protected:

			uint m_fcc;

		private:

	};





	///
	inline FCC::FCC():
	m_fcc('xyzw')
	{

	}


	///
	inline FCC::FCC(uint fcc):
	m_fcc(fcc)
	{

	}


	///
	inline FCC::FCC(const Helper::String &fcc)
	{

	}





	///
	inline void FCC::operator =(uint &fcc)
	{
		this->m_fcc = fcc;
	}


	///
	inline void FCC::operator =(const Helper::FCC &rhs)
	{

	}


	///
	inline bool FCC::operator !=(const Helper::FCC &rhs) const
	{
		return this->m_fcc != rhs.m_fcc;
	}


	///
	inline bool FCC::operator ==(const Helper::FCC &rhs) const
	{
		return this->m_fcc == rhs.m_fcc;
	}


	///
	inline bool FCC::operator <(const Helper::FCC &rhs) const
	{
		return this->m_fcc < rhs.m_fcc;
	}


	///
	inline bool FCC::operator <=(const Helper::FCC &rhs) const
	{
		return this->m_fcc <= rhs.m_fcc;
	}


	///
	inline bool FCC::operator >(const Helper::FCC &rhs) const
	{
		return this->m_fcc > rhs.m_fcc;
	}


	///
	inline bool FCC::operator >=(const Helper::FCC &rhs) const
	{
		return this->m_fcc >= rhs.m_fcc;
	}




	///
	inline void FCC::Set(uint &fcc)
	{
		this->m_fcc = fcc;
	}


	///
	inline void FCC::Set(const Helper::String & fcc)
	{
		this->m_fcc = uint(fcc[0] | fcc[1]<<8 | fcc[2]<<16 | fcc[3]<<24);
	}


	///
	inline bool FCC::IsValid() const 
	{
		return (this->m_fcc != 0);
	}


	///
	inline void FCC::Clear()
	{
		this->m_fcc = 0;
	}




	///
	inline uint FCC::GetAsUint() const
	{
		return this->m_fcc;
	}


	///
	inline Helper::String FCC::GetAsString() const
	{
		Helper::String result("xyzw");

		result[0] = ((this->m_fcc & 0xFF000000) << 24);
		result[1] = ((this->m_fcc & 0x00FF0000) << 16);
		result[2] = ((this->m_fcc & 0x0000FF00) << 8 );
		result[3] = ((this->m_fcc & 0x000000FF));

		return result;
	}





}

#endif // fcc_h__